var globalOptions = require('./globalOptions');
var GlobalErrorListener = require('./GlobalErrorListener');
var Element = require('./Element');
var NativeNode = require('./NativeNode');
var TextNode = require('./TextNode');
var ShadowRoot = require('./ShadowRoot');
var Component = require('./Component');
var Bind = require('./Bind');
var instruct = require('./instruct');
var FreeTmpl = function () {
};
FreeTmpl.prototype = Object.create(Object.prototype, {
    constructor: {
        value: FreeTmpl,
        writable: true,
        configurable: true
    }
});
var u = function () {
};
u.prototype = Object.create(Object.prototype, {
    constructor: {
        value: u,
        writable: true,
        configurable: true
    }
});
var p;
var g = null;
g = require('./precompiler');
p = require('./htmlParser');
FreeTmpl.precompiler = g;
FreeTmpl.htmlParser = p;
var _ = function (e) {
    return e.replace(/-([a-z])/g, function (e, t) {
        return t.toUpperCase();
    });
};
var hasOwnProperty = Object.prototype.hasOwnProperty;
var v = function (e, t) {
    if (null !== e && 'object' == typeof e && hasOwnProperty.call(e, t))
        return e[t];
};
var w = function (e, t, i, n) {
    if (hasOwnProperty.call(t, i)) {
        var r = t[i];
        if ('function' == typeof r)
            return GlobalErrorListener.safeCallback('Template Method', r, e, n);
    }
};
var m = function (e, t) {
    return [{
            t: 1,
            n: 'slot',
            a: [],
            c: [],
            p: null
        }];
};
var I = {
    t: 1,
    n: '"slot"',
    v: true,
    sn: '',
    a: [],
    c: [],
    p: null
};
var b = function (e, t, i) {
    e.classList.toggle(t, !!i);
};
var C = function (e, t, i) {
    e[t] = i;
};
var y = function (e, t, i) {
    var n = e.__dataProxy;
    n.scheduleReplace([t], i);
    n.doUpdates();
};
var E = function (e, t, i) {
    e.class = i;
};
var x = function (e, t, i) {
    e.setAttribute('style', i);
};
var B = function (e, t, i) {
    e.setAttribute('class', i);
};
var S = function (e, t, i) {
    e.textContent = i;
};
var Q = function (e, t, i) {
    e.dataset || (e.dataset = {});
    e.dataset[t] = i;
};
var k = {
    $: function (e, t, i) {
        if (true === i) {
            e.setAttribute(t, '');
        } else {
            false === i || null == i ? e.removeAttribute(t) : e.setAttribute(t, i);
        }
    },
    ':': C,
    c: b,
    s: function (e, t, i) {
        var n = e.style;
        n && (n[t] = i);
    },
    d: Q
};
var D = function (e, t, i) {
    return [{
            t: 1,
            n: 'slot',
            v: true,
            sn: '',
            a: [],
            c: []
        }];
};
FreeTmpl.create = function (e, t, i, n) {
    var r = undefined === e.template ? D : e.template;
    var o = r;
    if ('function' != typeof r)
        if (g && 'undefined' != typeof window && 'undefined' != typeof document) {
            var s = g.compile(r);
            var l = document.createElement('script');
            l.type = 'text/javascript';
            l.innerHTML = 'window.__exparserFreeTmpl=' + s;
            document.head.appendChild(l);
            document.head.removeChild(l);
            o = window.__exparserFreeTmpl;
            window.__exparserFreeTmpl = null;
        } else
            'undefined' != typeof process && undefined !== process.versions && undefined !== process.versions.node ? o = FreeTmpl.precompileAndGetCreator(r) : (GlobalErrorListener.hasGlobalWarningListeners() && GlobalErrorListener.triggerWarning('Non-precompiled template is not usable in this environment. Empty template is used instead.'), o = m);
    var d = Object.create(FreeTmpl.prototype);
    d._initValuesJSON = JSON.stringify(i);
    d._dataJSON = t !== i ? JSON.stringify(t) : null;
    d._tagTreeRoot = M(o, i, e.methods, n);
    d._renderingMode = n.renderingMode;
    return d;
};
var M = function (e, t, i, a) {
    var r = 'native' === a.renderingMode;
    var s = r;
    var l = false;
    var d = Object.create(null);
    r && !globalOptions.hasDOMBackend && (e = m);
    var A = {};
    var h = e(v, w, i);
    var u = function (e) {
        for (var i = 0; i < e.length; i++) {
            var n = e[i];
            if (3 !== n.t) {
                var a = n.n;
                var d = !(r || 'string' == typeof a && a.indexOf('-') < 0);
                'slot' === a && '' === n.sn && (l = true);
                n.n = a;
                var h = n.st;
                if (h && h.e) {
                    h.o = x;
                    s && (h.v = h.e(t, A, null));
                };
                var p = n.cl;
                if (p && p.e) {
                    p.o = r ? B : E;
                    s && (p.v = p.e(t, A, null));
                };
                var g = null;
                if (!d) {
                    n.p = g = r ? document.createElement(n.n) : NativeNode.create(n.n);
                    h && undefined !== h.v && g.setAttribute('style', h.v);
                    r && p && undefined !== p.v && g.setAttribute('class', p.v);
                };
                var f = n.a;
                for (var v = 0; v < f.length; v++) {
                    var w = f[v];
                    if (w.d)
                        r || instruct[w.n].register(w.n, w, n);
                    else {
                        if (!r) {
                            if ('bind' === w.n.slice(0, 4)) {
                                w.evCatch = false;
                                w.ev = _(w.n.slice(4));
                                ':' === w.ev[0] && (w.ev = w.ev.slice(1));
                            } else {
                                if ('catch' === w.n.slice(0, 5)) {
                                    w.evCatch = true;
                                    w.ev = _(w.n.slice(5));
                                    ':' === w.ev[0] && (w.ev = w.ev.slice(1));
                                };
                            }
                        };
                        var m = w.o;
                        if (d) {
                            if (m) {
                                w.o = '&' === m ? k[':'] : k[m];
                            } else {
                                w.o = k[':'];
                                w.n = _(w.n);
                            }
                            w.o === C && (w.o = y);
                            s && w.e && (w.v = w.e(t, A, null));
                        } else if (!w.ev) {
                            var I = k;
                            w.o = m ? '&' === m ? I[':'] : I[m] : I.$;
                            s ? (w.e && (w.v = w.e(t, A, null)), (w.o !== b || r) && w.o(g, w.n, w.v)) : w.e || w.o(g, w.n, w.v);
                        }
                    }
                }
                u(n.c);
                r && (1 !== n.c.length || undefined === n.c[0].sn || n.c[0].compressed || (n.sn = n.c[0].sn, n.compressed = true, n.c.pop()));
            } else
                n.e && (n.o = S, n.c = s ? n.e(t, A, null) : '');
        }
    };
    u(h, d, true);
    if (r) {
        l || h.push(I);
        1 !== h.length || '' !== h[0].sn || h[0].compressed || h.pop();
    };
    return h;
};
var N = function (e, t) {
    return function (i) {
        this[e](i);
        if (t)
            return false;
    };
};
var T = function (e, t, i, n, a, o, s, l) {
    var h = null;
    var u = 0;
    var p = null;
    for (var g = 0; g < e.length; g++) {
        var _ = s;
        var f = e[g];
        if (3 === f.t) {
            h = f.e ? t.createTextNode(f.e(n, a, null)) : t.createTextNode(f.c);
            f.e && Bind.addBindings(o, _, f.b, h, f);
            Element.appendChild(i, h);
        } else {
            var v = f.cl;
            var w = f.st;
            var m = f.a;
            var I = false;
            for (u = 0; u < m.length; u++)
                if ((p = m[u]).d) {
                    var E = instruct[p.n].create(p.n, p, f, n, a, o, _, l, t, T, i);
                    if (instruct[p.n].requireBlock) {
                        h = E;
                        Element.appendChild(i, h);
                        I = true;
                        break;
                    }
                }
            if (I)
                continue;
            if (f.v)
                h = t.createVirtualNode(f.n);
            else if (f.p) {
                h = t.cloneNativeNode(f.p);
                for (u = 0; u < m.length; u++)
                    (p = m[u]).d || (p.ev ? l(h, p.ev, p.v, p.evCatch) : p.o === C ? h.__domElement && (p.o(h.__domElement, p.n, p.e(n, a, null)), Bind.addBindings(o, _, p.b, h.__domElement, p)) : (p.e && p.o(h, p.n, p.e(n, a, null)), (p.e || p.o === b || p.o === Q) && Bind.addBindings(o, _, p.b, h, p)));
                if (w && w.e) {
                    h.setAttribute('style', w.e(n, a, null));
                    Bind.addBindings(o, _, w.b, h, w);
                };
            } else {
                if (f.cpf) {
                    var x = {};
                    var B = t.__wxHost;
                    for (var S in f.cpf)
                        !function (e) {
                            var t = f.cpf[e];
                            x[e] = B.__behavior.methods[t];
                        }(S);
                    t.__childrenPropsFilter = x;
                }
                h = t.createComponent(f.n, undefined, f.g, undefined);
                for (u = 0; u < m.length; u++)
                    if (!(p = m[u]).d) {
                        var k = p.v;
                        if (p.o === y && Component.hasPublicProperty(h, p.n)) {
                            if (p.e) {
                                k = p.e(n, a, null);
                                Bind.addBindings(o, _, p.b, h, p);
                            };
                            if (p.e) {
                                y(h, p.n, k);
                            } else {
                                h.__behavior.properties[p.n].type === Boolean ? y(h, p.n, true) : y(h, p.n, k);
                            }
                        } else {
                            if (p.ev) {
                                l(h, p.ev, k, p.evCatch);
                            } else {
                                if (p.o !== y) {
                                    if (p.e) {
                                        k = p.e(n, a, null);
                                        Bind.addBindings(o, _, p.b, h, p);
                                    };
                                    p.o(h, p.n, k);
                                };
                            }
                        }
                    }
                if (w) {
                    if (w.e) {
                        h.__domElement.setAttribute('style', w.e(n, a, null));
                        Bind.addBindings(o, _, w.b, h.__domElement, w);
                    } else {
                        h.__domElement.setAttribute('style', w.v);
                    }
                };
            }
            f.id && (h.id = f.id);
            if (v) {
                v.e ? h.class = v.e(n, a, null) : h.class = v.v;
                v.o && Bind.addBindings(o, _, v.b, h, v);
            };
            f.sl && (h.slot = f.sl);
            undefined !== f.sn && Element.setSlotName(h, f.sn);
            Element.appendChild(i, h);
            T(f.c, t, h, n, a, o, _, l);
        }
    }
};
var R = function (e, t, i) {
    var n = e.childNodes;
    for (var a = 0; a < n.length; a++) {
        var r = n[a];
        if (!(r instanceof TextNode)) {
            r.__id && (t[r.__id] = r);
            undefined !== r.__slotName && (i[r.__slotName] = r);
            R(r, t, i);
        };
    }
};
var L = function (e, t, i, n, a, r) {
    var o = null;
    var s = 0;
    var l = null;
    for (var d = 0; d < e.length; d++) {
        var c = e[d];
        if (undefined === c.n) {
            o = document.createTextNode(c.c);
            c.e && Bind.addBindings(a, r, c.b, o, c);
            t.appendChild(o);
        } else {
            var h = c.cl;
            var u = c.st;
            var p = c.a;
            o = c.v ? document.createElement('virtual') : document.importNode ? document.importNode(c.p, false) : c.p.cloneNode(false);
            for (s = 0; s < p.length; s++)
                (l = p[s]).e && Bind.addBindings(a, r, l.b, o, l);
            t.appendChild(o);
            c.id && (i[c.id] = o);
            h && h.e && Bind.addBindings(a, r, h.b, o, h);
            u && u.e && Bind.addBindings(a, r, u.b, o, u);
            undefined !== c.sn && (n[c.sn] = o);
            L(c.c, o, i, n, a, r);
        }
    }
};
FreeTmpl.prototype.createInstance = function (e) {
    var t = Object.create(u.prototype);
    var i = JSON.parse(this._initValuesJSON);
    var a = null === this._dataJSON ? i : JSON.parse(this._dataJSON);
    var r = Object.create(null);
    var o = Object.create(null);
    var s = [];
    var d = Bind.create('', null, null, null, null, [], function (e, t) {
    });
    var c = null;
    if ('native' === this._renderingMode) {
        'dom' === globalOptions.documentBackend && (c = document.createDocumentFragment());
        L(this._tagTreeRoot, c, r, o, d, {});
        o[''] || (o[''] = null);
    } else {
        c = ShadowRoot.create(e);
        if (e.ownerShadowRoot && e.ownerShadowRoot.__childrenPropsFilter)
            if (c.__childrenPropsFilter)
                for (var h in e.ownerShadowRoot.__childrenPropsFilter)
                    c.__childrenPropsFilter[h] || (c.__childrenPropsFilter[h] = e.ownerShadowRoot.__childrenPropsFilter[h]);
            else
                c.__childrenPropsFilter = e.ownerShadowRoot.__childrenPropsFilter;
        T(this._tagTreeRoot, c, c, i, {}, d, {}, function (e, t, i, n) {
            c.__wxHost ? e.addListener(t, N(i, n).bind(c.__wxHost)) : s.push({
                target: e,
                name: t,
                func: N(i, n)
            });
        });
        R(c, r, o);
    }
    t.data = a;
    t.shadowRoot = c;
    t.idMap = r;
    t.slots = o;
    t.listeners = s;
    t._topScope = d;
    return t;
};
u.prototype.updateValues = function (e, t, i) {
    var n = Element.getMethodCaller(e);
    for (var a = 0; a < i.length; a++) {
        var o = i[a];
        Bind.updateBinding(this._topScope, o, t, {}, n);
    }
};
module.exports = FreeTmpl;
